<template>
  <FModal width="1200" bodyHeight="500px" @ok="saveRelations"
          ref="refModal" header="字段映射配置">
    <template v-slot:contentHeader>
      <div style="margin: 0 0 10px 0">
        <el-select v-model="relationFormName" clearable filterable
                   placeholder="请选择单据" @change="relationFormNameChange">
          <el-option v-for="opt in formDefinitions" :key="opt.formName"
                     :label="opt.showName" :value="opt.formName"/>
        </el-select>
        <el-button icon="add" type="primary" :disabled="isEmpty(relationFormName)"
                   plain style="margin-left: 10px" round @click="addNew">添加字段映射
        </el-button>
      </div>
      <div style="padding-bottom: 10px">
        <ViewActionConfiguration :views="views" :flows="flows" ref="refViewActionConfiguration"
                                 :view-actions="viewActions" :obj="edittingButton"/>
      </div>
    </template>
    <el-table :data="relations" border stripe height="100%" v-loading="loading">
      <el-table-column show-overflow-tooltip prop="appName" align="center" label="本表单数据域">
        <template #default="{row}">
          <el-select filterable @change="() => sourceFieldChange(row)" style="width: 100%"
                     clearable v-model="row.sourceFormFieldId" placeholder="请选择数据域">
            <el-option v-for="opt in leftFieldSelection"
                       :key="opt.id" :label="opt.showName" :value="opt.id"/>
          </el-select>
        </template>
      </el-table-column>
      <el-table-column show-overflow-tooltip width="100" prop="appName" align="center" label=" ">
        <div style="display: flex; align-items: center; justify-content: center">
          <right style="width: 20px"/>
        </div>
      </el-table-column>
      <el-table-column show-overflow-tooltip prop="appName" align="center" label="目标表单数据域">
        <template #default="{row}">
          <el-select filterable style="width: 100%" @change="() => targetFieldChange(row)"
                     clearable v-model="row.targetFormFieldId" placeholder="请选择数据域">
            <el-option v-for="opt in rightFieldSelection"
                       :key="opt.id" :label="opt.showName" :value="opt.id"/>
          </el-select>
        </template>
      </el-table-column>

      <el-table-column show-overflow-tooltip prop="appName" width="160px"
                       align="center" label="操作">
        <template #default="{row}">
          <el-button icon="up" circle size="small" @click="() => moveUp(row)"/>
          <el-button icon="down" circle size="small" @click="() => moveDown(row)"/>
          <el-popconfirm title="删除后不可恢复, 确实删除?" @confirm="() => remove(row)">
            <template #reference>
              <el-button icon="remove" circle type="warning" size="small"/>
            </template>
          </el-popconfirm>
        </template>
      </el-table-column>
    </el-table>
  </FModal>
</template>
<script setup>
import FModal from '@/components/FModal/index.vue';
import {onMounted, ref, shallowRef, toRaw, unref} from 'vue';
import {DefaultButtonRelation, DefaultFormDefinition, DefaultMenuButton} from '@/components/form/DefaultFormDefinition';
import {isEmpty, isEmptyThrow, isNotEmpty} from '@/utils/CommonUtils';
import {getAction} from '@/request/BaseRequest';
import {Right} from '@element-plus/icons-vue';
import FormDefinitionHelper from '@/components/form/FromDesigner/FormDefinitionHelper';
import {ElMessage, ElMessageBox} from 'element-plus';
import ViewActionConfiguration from '@/components/form/FormMenuButtonConfiguration/ViewActionConfiguration.vue';
import FormFieldCopyChecker from '@/components/form/FromDesigner/FormFieldCopyChecker';

const props = defineProps({
  edittingButton: DefaultMenuButton,
  formDefinition: JSON.parse(JSON.stringify(DefaultFormDefinition))
});
const relations = ref([]);
const refModal = shallowRef();
const formDefinitions = shallowRef([]);
const relationFormName = shallowRef();
const loading = shallowRef(false);
const lastRelationFormName = shallowRef();
const leftFieldSelection = shallowRef([]);
const rightFieldSelection = shallowRef([]);
const views = shallowRef([]);
const flows = shallowRef([]);
let viewActions = [];
const refViewActionConfiguration = shallowRef();

onMounted(() => {
  loadFormDefinitions();
});

function relationFormNameChange() {
  if (relations.value.length > 0) {
    ElMessageBox.confirm('修改单据类型, 将清空字段映射', '确定修改吗', {
      draggable: true,
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning',
    }).then(() => {
      relations.value = [];
      lastRelationFormName.value = relationFormName.value;
      props.edittingButton.pcViewId = undefined;
      props.edittingButton.mobileViewId = undefined;
      props.edittingButton.pcViewActionId = undefined;
      props.edittingButton.mobileViewActionId = undefined;
      loadRightFormFields();
      refViewActionConfiguration.value.clear();
    }).catch(() => {
      relationFormName.value = lastRelationFormName.value;
    });
  } else {
    relations.value = [];
    lastRelationFormName.value = relationFormName.value;
    props.edittingButton.pcViewId = undefined;
    props.edittingButton.mobileViewId = undefined;
    props.edittingButton.pcViewActionId = undefined;
    props.edittingButton.mobileViewActionId = undefined;
    refViewActionConfiguration.value.clear();
    loadRightFormFields();
  }
}

function loadRightFormFields() {
  if (isEmpty(relationFormName.value)) return;

  if (relationFormName.value === props.formDefinition.formName) {
    rightFieldSelection.value = leftFieldSelection.value;
    flows.value = props.formDefinition.flows;
    return;
  }
  loading.value = true;
  getAction('/plat/loadFormDefinitionFieldsForMenuButton',
      {formName: relationFormName.value}).then(data => {
    if (data.success) {
      loading.value = false;
      rightFieldSelection.value = data.result.fields;
      views.value = data.result.views;
      flows.value = data.result.flows;
      viewActions = data.result.viewActions;
    }
  });
}

function loadFormDefinitions() {
  loadFormDefinitionsForMenuButton();
}

function loadFormDefinitionsForMenuButton() {
  getAction('/plat/loadFormDefinitionsForMenuButton').then(data => {
    if (data.success) {
      let result = data.result;
      setFormDefinitionOptions(result);
    }
  });
}

function addNew() {
  let relation = JSON.parse(JSON.stringify(DefaultButtonRelation));
  relations.value.push(relation);
}

function getFormRelationDefinition() {
  if (relationFormName === props.formDefinition.formName) return toRaw(props.formDefinition);

  let forms = formDefinitions.value.filter(form => form.formName === relationFormName.value);
  if (isEmpty(forms)) return undefined;
  return forms[0];
}

function targetFieldChange(row) {
  let list = unref(rightFieldSelection);
  list.forEach(f => {
    if (f.id === row.targetFormFieldId) {
      row.targetFormField = f.fieldName;
      row.targetFormFieldComponent = f.component;

      row.targetFormId = f.formId;
      row.targetFormName = f.formName;
      row.targetParentFormName = f.parentFormName;
      row.targetMainField = row.targetFormName === row.targetParentFormName;
    }
  });

  if (!checkCopyAble(row)) {
    row.targetFormFieldId = undefined;
    row.targetMainField = undefined;
  }
}

function sourceFieldChange(row) {
  let list = unref(leftFieldSelection);
  list.forEach(f => {
    if (f.id === row.sourceFormFieldId) {
      row.sourceFormField = f.fieldName;
      row.sourceFormFieldComponent = f.component;

      row.sourceFormId = f.formId;
      row.sourceFormName = f.formName;
      row.sourceParentFormName = f.parentFormName;
      row.sourceMainField = row.sourceFormName === row.sourceParentFormName;
    }
  });


  if (!checkCopyAble(row)) {
    row.sourceFormFieldId = undefined;
    row.sourceMainField = undefined;
  }
}

function checkComponentCopyAble(row) {
  let field1 = leftFieldSelection.value.find(f => f.id === row.sourceFormFieldId);
  let field2 = rightFieldSelection.value.find(f => f.id === row.targetFormFieldId);
  let res = FormFieldCopyChecker.checkCopyAble(field1, field2);
  if (isEmpty(res)) {
    return true;
  }
  ElMessage({
    showClose: true,
    message: res,
    type: 'warning',
  });
  return false;
}

function checkCopyAble(row) {
  if (row.sourceMainField === false && row.targetMainField === true) {
    ElMessage({
      showClose: true,
      message: '子表的字段不能往主表上复制',
      type: 'warning',
    });
    return false;
  }

  if (isEmpty(row.sourceFormFieldId) || isEmpty(row.targetFormFieldId)) {
    //其中一个字段没有选
  } else {
    if (checkDuplicate(row)) {
      ElMessage({
        showClose: true,
        message: '字段映射出现重复',
        type: 'warning',
      });
      return false;
    }

    if (checkTargetFieldDuplicate(row)) {
      ElMessage({
        showClose: true,
        message: '目标字段出现重复映射',
        type: 'warning',
      });
      return false;
    }
    return checkComponentCopyAble(row);
  }

  return true;
}

function checkTargetFieldDuplicate(row) {
  let set = new Set();
  let list = unref(relations);
  if (isEmpty(list)) return false;
  for (let i = 0; i < list.length; i++) {
    set.add(list[i].targetFormFieldId);
  }
  return set.size !== list.length;
}

function checkDuplicate(row) {
  let list = unref(relations);
  if (isEmpty(list)) return false;
  for (let i = 0; i < list.length; i++) {
    if (list[i] === row) continue;
    if (list[i].sourceFormFieldId === row.sourceFormFieldId
        && list[i].targetFormFieldId === row.targetFormFieldId) {
      return true;
    }
  }
}

function setFormDefinitionOptions(forms) {
  forms = forms.filter(f => f.id !== props.formDefinition.id);
  forms.push({
    id: props.formDefinition.id,
    formName: props.formDefinition.formName,
    showName: '本表单'
  });
  formDefinitions.value = forms;
}

function open() {
  refModal.value.open();
  loadLeftFieldSelection();
  setRelations();
}

function loadLeftFieldSelection() {
  let helper = new FormDefinitionHelper(toRaw(props.formDefinition));
  leftFieldSelection.value = helper.getAllFieldsLeftForRelationMenuButton(); //代码写到这里了!!!
}

function setRelations() {
  if (isEmpty(props.edittingButton)) return;

  if (isEmpty(props.edittingButton.relations)) {
    relations.value = props.edittingButton.relations = [];
    return;
  }
  relations.value = JSON.parse(JSON.stringify(toRaw(props.edittingButton.relations)));
  if (isNotEmpty(relations.value)) {
    relationFormName.value = relations.value[0].targetParentFormName;
  }
  loadRightFormFields();
}

defineExpose({
  open
});

function resolveSelectedFields() {
  let list = unref(relations);
  if (isEmpty(list)) list = [];
  let formDefinition = getFormRelationDefinition();
  isEmptyThrow(formDefinition, 'formDefinition不能为空');
}

function saveRelations() {
  checkRelations().then(() => {
    resolveSelectedFields();
    props.edittingButton.relations = unref(relations);
    relations.value = [];
    leftFieldSelection.value = [];
    rightFieldSelection.value = [];
    refModal.value.close();
  });
}

function checkRelations() {
  return new Promise((success, err) => {
    let list = unref(relations);
    if (isEmpty(list)) {
      ElMessage({
        showClose: true,
        message: '请添加字段映射',
        type: 'warning',
      });
      return;
    }

    for (let i = 0; i < list.length; i++) {
      if (isEmpty(list[i].sourceFormFieldId)
          || isEmpty(list[i].targetFormFieldId)) {
        ElMessage({
          showClose: true,
          message: '请设置每一行的字段映射',
          type: 'warning',
        });
        return;
      }
    }

    if (isEmpty(flows)) {
      if (isEmpty(props.edittingButton.pcViewId) ||
          isEmpty(props.edittingButton.pcViewActionId) ||
          isEmpty(props.edittingButton.mobileViewId) ||
          isEmpty(props.edittingButton.mobileViewActionId)) {
        ElMessage({
          showClose: true,
          message: '请选择流程或视图',
          type: 'warning',
        });
        return;
      }
    } else {
      if (isEmpty(props.edittingButton.processDefinitionId)) {
        ElMessage({
          showClose: true,
          message: '请选择流程或视图',
          type: 'warning',
        });
        return;
      }
    }
    success();
  });
}

function moveUp(row) {
  let index = relations.value.findIndex(r => r === row);
  if (index > 0) {
    [relations.value[index - 1], relations.value[index]] = [relations.value[index], relations.value[index - 1]];
  }
}

function moveDown(row) {
  let index = relations.value.findIndex(r => r === row);
  if (index < relations.value.length - 1) {
    [relations.value[index - 1], relations.value[index]] = [relations.value[index], relations.value[index - 1]];
  }
}

function remove(row) {
  let index = relations.value.findIndex(r => r === row);
  if (index === -1) return;
  relations.value.splice(index, 1);
}
</script>
<style>
.f-modal-small-body .relation-config-wrapper {
  height: 500px;
  overflow: auto;
}

.f-modal-fullscreen-body .relation-config-wrapper {
  height: 100%;
}
</style>
